package org.example.service;

import cn.hutool.core.text.StrFormatter;
import lombok.extern.slf4j.Slf4j;
import org.example.dao.DbInfoDao;
import org.example.model.config.AnalysisConfig;
import org.example.model.entity.TableInfo;
import org.example.model.entity.ColumnInfo;
import org.example.model.entity.ColumnRelation;
import org.example.model.entity.TableStatusInfo;

import java.sql.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据库信息服务类
 */
@Slf4j
public class DbInfoService {
    private final DbInfoDao dbInfoDao;
    private final AnalysisConfig analysisConfig;
    private final DbService dbService = new DbService();

    public DbInfoService(Properties props, String sqliteDbPath, AnalysisConfig analysisConfig) {
        this.dbInfoDao = new DbInfoDao(props, sqliteDbPath);
        this.analysisConfig = analysisConfig;
    }

    public void collectDbInfo() {
        try {
            // 获取所有表信息
            List<TableInfo> tables = getSourceTableInfo();

            // 保存到SQLite
            if (analysisConfig.isSavaTableInfo()) {
                dbService.saveTableBatch(tables);
            }
            // 保存所有字段信息
            if (analysisConfig.isSaveColumnInfo()) {
                List<ColumnInfo> allColumns = new ArrayList<>();
                for (TableInfo table : tables) {
                    if (table.getColumnInfos() != null) {
                        allColumns.addAll(table.getColumnInfos());
                    }
                }
                allColumns.stream().forEach(columnInfo -> {
                    columnInfo.setProjectName(analysisConfig.getProjectName());
                });
                dbService.saveColumnInfoBatch(allColumns);
            }
        } catch (Exception e) {
            log.error("收集数据库信息失败", e);
            throw new RuntimeException("收集数据库信息失败", e);
        }
    }

    private List<TableInfo> getSourceTableInfo() throws SQLException {
        List<TableInfo> tables = new ArrayList<>();
        Map<String, List<ColumnInfo>> columnMap = new HashMap<>();
        try (Connection conn = dbInfoDao.getSourceConnection()) {
            DatabaseMetaData metaData = conn.getMetaData();
            ResultSet rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
            // 1. 先获取所有表名
            List<String> tableNames = new ArrayList<>();
            while (rs.next()) {
                tableNames.add(rs.getString("TABLE_NAME"));
            }
            log.info("发现{}张表", tableNames.size());
            // 2. 一次性获取所有字段信息
            List<ColumnInfo> allColumns = getColumnInfo(conn, analysisConfig.getTABLE_SCHEMA());
            // 3. 按表名分组
            columnMap = allColumns.stream().collect(java.util.stream.Collectors.groupingBy(ColumnInfo::getTableName));
            List<TableInfo> allTables = getAllTables(conn, analysisConfig.getTABLE_SCHEMA());
            Map<String,TableStatusInfo> tableStatusMap = getAllTableStatus(conn).stream().collect(Collectors.toMap(TableStatusInfo::getName,a->a));
            // 4. 构建TableInfo对象
            for (TableInfo table : allTables) {
                table.setIsActive(true);
                List<ColumnInfo> columns = columnMap.getOrDefault(table.getTableName(), Collections.emptyList());
                table.setColumnInfos(columns);
                table.setColumnCount(columns.size());
                if(tableStatusMap.containsKey(table.getTableName())){
                    TableStatusInfo  tableStatusInfo = tableStatusMap.get(table.getTableName());
                    table.setRowCount(tableStatusInfo.getRows());
                    table.setTableComment(tableStatusInfo.getComment());
                    table.setLastUpdateTime(tableStatusInfo.getUpdateTime());
                }
                tables.add(table);
            }
        }
        return tables;
    }

    private List<ColumnInfo> getColumnInfo(Connection conn, String TABLE_SCHEMA) {
        String sql = StrFormatter.format(
                "select * from INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA='{}';", TABLE_SCHEMA);
        List<ColumnInfo> columns = new ArrayList<>();

        try (PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                try {
                    ColumnInfo column = new ColumnInfo();
                    // 下面字段名请根据你的数据库实际情况调整
                    column.setTableName(rs.getString("TABLE_NAME"));
                    column.setColumnName(rs.getString("COLUMN_NAME"));
                    column.setColumnType(rs.getString("DATA_TYPE"));
                    column.setColumnSize(rs.getLong("CHARACTER_MAXIMUM_LENGTH"));
                    column.setNullable("YES".equalsIgnoreCase(rs.getString("IS_NULLABLE")));
                    column.setColumnKey(rs.getString("COLUMN_KEY"));
                    column.setColumnDefault(rs.getString("COLUMN_DEFAULT"));
                    column.setColumnComment(rs.getString("COLUMN_COMMENT"));
                    column.setOrdinalPosition(rs.getInt("ORDINAL_POSITION"));
                    // 业务逻辑字段
                    column.setIsDisplay(true); // 可根据实际业务判断
                    column.setDisplayOrder(rs.getInt("ORDINAL_POSITION"));
                    column.setCreatedAt(null); // 可根据需要设置
                    column.setRefreshable(true); // 默认可刷新
                    column.setProjectName(analysisConfig.getProjectName());
                    columns.add(column);
                } catch (Exception e) {
                    log.error("获取表{}的字段信息失败", rs.getString("TABLE_NAME"));
                }
            }
        } catch (SQLException e) {
            log.error("获取表{}的字段信息失败", e);
        }
        return columns;
    }

    private List<TableInfo> getAllTables(Connection conn, String TABLE_SCHEMA) throws SQLException {
        String sql = StrFormatter.format(
                "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='{}';", TABLE_SCHEMA);
        List<TableInfo> tables = new ArrayList<>();
        try (PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                TableInfo table = new TableInfo();
                table.setTableName(rs.getString("TABLE_NAME"));
                table.setTableComment(rs.getString("TABLE_COMMENT"));
                table.setRowCount(rs.getLong("TABLE_ROWS"));
                table.setIsActive(true); // 默认激活
                table.setLastUpdateTime(rs.getTimestamp("UPDATE_TIME") != null
                        ? rs.getTimestamp("UPDATE_TIME").toLocalDateTime()
                        : null);
                table.setCreatedAt(rs.getTimestamp("CREATE_TIME") != null
                        ? rs.getTimestamp("CREATE_TIME").toLocalDateTime()
                        : null);
                // 可根据需要设置projectName/moduleName等
                table.setProjectName(analysisConfig.getProjectName());
                // 其他字段可根据需要补充
                tables.add(table);
            }
        }
        return tables;
    }

    public List<TableStatusInfo> getAllTableStatus(Connection conn) throws SQLException {
        String sql = "SHOW TABLE STATUS";
        List<TableStatusInfo> statusList = new ArrayList<>();
        try (PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                TableStatusInfo info = new TableStatusInfo();
                info.setName(rs.getString("Name"));
                info.setEngine(rs.getString("Engine"));
                info.setVersion(rs.getLong("Version"));
                info.setRowFormat(rs.getString("Row_format"));
                info.setRows(rs.getLong("Rows"));
                info.setAvgRowLength(rs.getLong("Avg_row_length"));
                info.setDataLength(rs.getLong("Data_length"));
                info.setMaxDataLength(rs.getLong("Max_data_length"));
                info.setIndexLength(rs.getLong("Index_length"));
                info.setDataFree(rs.getLong("Data_free"));
                info.setAutoIncrement(rs.getLong("Auto_increment"));
                info.setCreateTime(rs.getTimestamp("Create_time") != null ? rs.getTimestamp("Create_time").toLocalDateTime() : null);
                info.setUpdateTime(rs.getTimestamp("Update_time") != null ? rs.getTimestamp("Update_time").toLocalDateTime() : null);
                info.setCheckTime(rs.getTimestamp("Check_time") != null ? rs.getTimestamp("Check_time").toLocalDateTime() : null);
                info.setCollation(rs.getString("Collation"));
                info.setChecksum(rs.getString("Checksum"));
                info.setCreateOptions(rs.getString("Create_options"));
                info.setComment(rs.getString("Comment"));
                statusList.add(info);
            }
        }
        return statusList;
    }
} 